package com.neoCalf.neoFriend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.neoCalf.neoCommon.entity.*;
import com.neoCalf.neoCommon.enums.*;
import com.neoCalf.neoCommon.exception.BusinessException;
import com.neoCalf.neoCommon.model.R;
import com.neoCalf.neoCommon.model.dto.*;
import com.neoCalf.neoCommon.model.vo.GroupInitData;
import com.neoCalf.neoCommon.utils.DataTool;
import com.neoCalf.neoCommon.utils.Md5Util;
import com.neoCalf.neoCommon.utils.SendUtils;
import com.neoCalf.neoCommon.utils.SessionSeq;
import com.neoCalf.neoFriend.feigns.ChatServiceFeign;
import com.neoCalf.neoFriend.feigns.GroupServiceFeign;
import com.neoCalf.neoFriend.feigns.UserServiceFeign;
import com.neoCalf.neoFriend.mapper.UserContactApplyMapper;
import com.neoCalf.neoFriend.mapper.UserContactMapper;
import com.neoCalf.neoFriend.service.ContactService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * @author 小牛
 * @version 1.0
 * @description TODO
 * @date 2025/4/13 21:22
 */
@Service
@Slf4j
public class ContactServiceImpl extends ServiceImpl<UserContactMapper, UserContact> implements ContactService {
    @Resource
    private UserContactMapper userContactMapper;
    @Autowired
    private ChatServiceFeign chatServiceFeign;
    @Autowired
    private SessionSeq sessionSeq;
    @Autowired
    private SendUtils sendUtils;
    @Autowired
    private UserContactApplyMapper userContactApplyMapper;
    @Autowired
    private UserServiceFeign userServiceFeign;
    @Autowired
    private GroupServiceFeign groupServiceFeign;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRobotContact(UserContact userContact) {
        int insert = userContactMapper.insert(userContact);
        DataTool.checkAffectRow(insert, "添加联系人失败");

        String sessionId = Md5Util.Md5Method(new String[]{userContact.getUserId(), userContact.getContactId()});
        chatServiceFeign.addSession(new Session(userContact.getUserId(), userContact.getContactId(), sessionId, userContact.getContactName()));

        chatServiceFeign.addChatSession(new ChatSession(sessionId, userContact.getWelcomeMessage(), userContact.getCreateTime()));

        List<ChatMessage> chatMessageList = new ArrayList<>();
        ChatMessage chatMessage = new ChatMessage(
                sessionSeq.next(sessionId),
                sessionId,
                MessageTypeEnum.ADD_FRIEND.getType(),
                MessageTypeEnum.ADD_FRIEND.getInitMessage(),
                userContact.getContactId(),
                userContact.getContactName(),
                userContact.getCreateTime(),
                userContact.getUserId(),
                UserContactTypeEnum.USER.getType(),
                MessageStatusEnum.FLUSH.getStatus()
        );
        ChatMessage chatMessage2 = new ChatMessage(
                sessionSeq.next(sessionId),
                sessionId,
                MessageTypeEnum.CHAT.getType(),
                userContact.getWelcomeMessage(),
                userContact.getContactId(),
                userContact.getContactName(),
                userContact.getCreateTime(),
                userContact.getUserId(),
                UserContactTypeEnum.USER.getType(),
                MessageStatusEnum.FLUSH.getStatus()
        );
        chatMessageList.add(chatMessage);
        chatMessageList.add(chatMessage2);
        chatServiceFeign.addChatMessageList(chatMessageList);
    }

    @Override
    public List<UserContact> selectContactList(String userId) {
        LambdaQueryWrapper<UserContact> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserContact::getUserId, userId);
        return userContactMapper.selectList(queryWrapper);
    }

    @Override
    public List<UserContactApply> selectUserContactApplyList(String userId) {
        LambdaQueryWrapper<UserContactApply> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserContactApply::getReceiveUserId, userId);
        queryWrapper.eq(UserContactApply::getStatus, ContactApplyStatusEnum.INIT.getStatus());
        return userContactApplyMapper.selectList(queryWrapper);
    }

    @Override
    public UserContact findUserContact(String userId, String contactId) {
        LambdaQueryWrapper<UserContact> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserContact::getUserId, userId);
        queryWrapper.eq(UserContact::getContactId, contactId);
        return userContactMapper.selectOne(queryWrapper);
    }

    @Override
    public List<UserContact> findUserContactByType(String userId, Integer contactType) {
        LambdaQueryWrapper<UserContact> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserContact::getUserId, userId);
        queryWrapper.eq(UserContact::getContactType, contactType);
        return userContactMapper.selectList(queryWrapper);
    }

    @Override
    public Long findMyContactCount(String userId, Integer[] typeList) {
        LambdaQueryWrapper<UserContact> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserContact::getUserId, userId);
        queryWrapper.in(UserContact::getContactType, typeList);
        return userContactMapper.selectCount(queryWrapper);
    }

    @Override
    public Long findGroupMemberCount(String groupId) {
        LambdaQueryWrapper<UserContact> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserContact::getContactId, groupId);
        queryWrapper.eq(UserContact::getContactType, UserContactTypeEnum.GROUP.getType());
        return userContactMapper.selectCount(queryWrapper);
    }

    @Override
    public List<UserContact> findGroupMember(String groupId) {
        LambdaQueryWrapper<UserContact> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserContact::getContactId, groupId);
        queryWrapper.eq(UserContact::getContactType, UserContactTypeEnum.GROUP.getType());
        return userContactMapper.selectList(queryWrapper);
    }

    @Override
    public List<UserContact> loadContact(String userId, UserContactTypeEnum typeEnum) {
        return userContactMapper.selectListByUserIdAndContactType(userId, typeEnum.getType(), true);
    }

    @Override
    public void addContact2BlackList(String userId, String contactId) {
        LambdaUpdateWrapper<UserContact> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(UserContact::getUserId, userId);
        updateWrapper.eq(UserContact::getContactId, contactId);
        updateWrapper.eq(UserContact::getStatus, UserContactStatusEnum.FRIEND.getStatus());
        updateWrapper.set(UserContact::getStatus, UserContactStatusEnum.BLACKLIST.getStatus());
        int update = userContactMapper.update(null, updateWrapper);
        DataTool.checkAffectRow(update, "他不是你的好友，无法拉黑");
    }

    @Override
    public void removeContact2BlackList(String userId, String contactId) {
        LambdaUpdateWrapper<UserContact> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(UserContact::getUserId, userId);
        updateWrapper.eq(UserContact::getContactId, contactId);
        updateWrapper.eq(UserContact::getStatus, UserContactStatusEnum.BLACKLIST.getStatus());
        updateWrapper.set(UserContact::getStatus, UserContactStatusEnum.FRIEND.getStatus());
        int update = userContactMapper.update(null, updateWrapper);
        DataTool.checkAffectRow(update);
    }

    @Override
    public void delContact(String userId, String contactId) {
        LambdaQueryWrapper<UserContact> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserContact::getUserId, contactId);
        queryWrapper.eq(UserContact::getContactId, userId);
        UserContact userContact = userContactMapper.selectOne(queryWrapper);
        if (userContact == null) {
            queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserContact::getUserId, userId);
            queryWrapper.eq(UserContact::getContactId, contactId);
            userContactMapper.delete(queryWrapper);
            chatServiceFeign.delContactSession(Md5Util.Md5Method(new String[]{userId, contactId}));
        }
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserContact::getUserId, userId);
        queryWrapper.eq(UserContact::getContactId, contactId);
        int update = userContactMapper.delete(queryWrapper);
        DataTool.checkAffectRow(update, "删除联系人失败");
    }

    @Override
    public UserInfoDto contactInfo(String userId, String contactId) {
        UserContactTypeEnum contactTypeEnum = DataTool.getContactTypeEnum(contactId);
        if (contactTypeEnum == UserContactTypeEnum.USER ||
                contactTypeEnum == UserContactTypeEnum.ROBOT ||
                contactTypeEnum == UserContactTypeEnum.SYSTEM) {
            UserInfoDto result = userServiceFeign.findUserInfo4(contactId).getResult();
            if (result != null) {
                LambdaQueryWrapper<UserContact> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(UserContact::getUserId, userId);
                queryWrapper.eq(UserContact::getContactId, contactId);
                UserContact userContact = userContactMapper.selectOne(queryWrapper);
                result.setStatus(userContact.getStatus());
            }
            return result;
        }
        return null;
    }

    @Override
    public SearchContactResultDto search(String userId, String contactId) {
        UserContactTypeEnum TypeEnum = UserContactTypeEnum.getByPrefix(contactId.substring(0, 1));
        if (TypeEnum == null) {
            throw new BusinessException(ResultCode.BusinessError, "联系人类型错误");
        }
        if (userId.equals(contactId)) {
            return null;
        }
        switch (TypeEnum) {
            case USER:
            case ROBOT:
            case SYSTEM:
                R<UserInfoDto> userInfo4R = userServiceFeign.findUserInfo4(contactId);
                if (!userInfo4R.getCode().equals(ResultCode.Success.getCode()) || userInfo4R.getResult() == null || userInfo4R.getResult().getUserInfo() == null) {
                    return null;
                }
                UserInfo userInfo = userInfo4R.getResult().getUserInfo();
                SearchContactResultDto searchContactResultDto = new SearchContactResultDto();
                searchContactResultDto.setUserId(userInfo.getUserId());
                searchContactResultDto.setContactType(DataTool.getContactTypeEnum(contactId).getType());
                searchContactResultDto.setNickName(userInfo.getNickName());
                searchContactResultDto.setSex(userInfo.getSex());
                searchContactResultDto.setAvatar(userInfo.getAvatar());
                searchContactResultDto.setAreaName(userInfo.getAreaName());
                // 状态查询
                UserContact userContact = userContactMapper.selectOne(new LambdaQueryWrapper<UserContact>().eq(UserContact::getUserId, userId).eq(UserContact::getContactId, contactId));
                UserContact userContact1 = userContactMapper.selectOne(new LambdaQueryWrapper<UserContact>().eq(UserContact::getUserId, contactId).eq(UserContact::getContactId, userId));
                if (userContact != null && userContact1 != null) {
                    searchContactResultDto.setStatus(userContact.getStatus());
                    searchContactResultDto.setToStatus(userContact1.getStatus());
                }
                if (userContact1 == null && userContact == null) {
                    // 未添加
                    searchContactResultDto.setStatus(UserContactStatusEnum.NOT_FRIEND.getStatus());
                    searchContactResultDto.setToStatus(UserContactStatusEnum.NOT_FRIEND.getStatus());
                }
                if (userContact1 != null && userContact == null) {
                    // 对方已添加
                    searchContactResultDto.setStatus(UserContactStatusEnum.DEL.getStatus());
                    searchContactResultDto.setToStatus(userContact1.getStatus());
                }
                if (userContact1 == null && userContact != null) {
                    // 我已添加
                    searchContactResultDto.setStatus(userContact.getStatus());
                    searchContactResultDto.setToStatus(UserContactStatusEnum.DEL.getStatus());
                }
                return searchContactResultDto;
            case GROUP:
                R<GroupInfo> groupInfoR = groupServiceFeign.getGroupInfo(contactId);
                if (!groupInfoR.getCode().equals(ResultCode.Success.getCode()) || groupInfoR.getResult() == null) {
                    return null;
                }
                GroupInfo groupInfo = groupInfoR.getResult();
                SearchContactResultDto searchContactResultDto1 = new SearchContactResultDto();
                searchContactResultDto1.setUserId(groupInfo.getGroupId());
                searchContactResultDto1.setContactType(TypeEnum.getType());
                searchContactResultDto1.setNickName(groupInfo.getGroupName());
                searchContactResultDto1.setAvatar(groupInfo.getAvatar());
                searchContactResultDto1.setStatus(UserContactStatusEnum.NOT_FRIEND.getStatus());
                userContact = userContactMapper.selectOne(new LambdaQueryWrapper<UserContact>().eq(UserContact::getUserId, userId).eq(UserContact::getContactId, contactId));
                if (userContact != null) {
                    searchContactResultDto1.setStatus(userContact.getStatus());
                }
                searchContactResultDto1.setToStatus(groupInfo.getStatus());
                return searchContactResultDto1;
            default:
                throw new BusinessException(ResultCode.BusinessError, "联系人类型错误");
        }
    }

    @Override
    public List<UserContactApply> loadContactApply(String userId) {
        LambdaQueryWrapper<UserContactApply> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserContactApply::getReceiveUserId, userId);
        queryWrapper.orderByDesc(UserContactApply::getLastApplyTime);
        return userContactApplyMapper.selectList(queryWrapper);
    }

    @Override
    public void addGroupContact(UserContact userContact) {
        int insert = userContactMapper.insert(userContact);
        DataTool.checkAffectRow(insert);

        String sessionId = Md5Util.Md5Method(new String[]{userContact.getContactId()});
        Session session = new Session(userContact.getUserId(), userContact.getContactId(), sessionId, userContact.getContactName());
        chatServiceFeign.addSession(session);

        ChatSession chatSession = new ChatSession(sessionId, userContact.getWelcomeMessage(), userContact.getCreateTime());
        chatServiceFeign.addChatSession(chatSession);

        ArrayList<ChatMessage> chatMessageList = new ArrayList<>();
        ChatMessage chatMessage = new ChatMessage(
                sessionSeq.next(sessionId),
                sessionId,
                MessageTypeEnum.GROUP_CREATE.getType(),
                MessageTypeEnum.GROUP_CREATE.getInitMessage(),
                userContact.getContactId(),
                userContact.getContactName(),
                userContact.getCreateTime(),
                userContact.getUserId(),
                UserContactTypeEnum.GROUP.getType(),
                MessageStatusEnum.FLUSH.getStatus()
        );
        chatMessageList.add(chatMessage);
        chatServiceFeign.addChatMessage(chatMessage);
        session.setChatSession(chatSession);

        SendMessageDto<GroupInitData> sendMessageDto = new SendMessageDto<>();
        GroupInitData groupInitData = new GroupInitData(session, chatMessageList);
        sendMessageDto.setExtendData(groupInitData);
        sendMessageDto.setMessageType(MessageTypeEnum.GROUP_CREATE.getType());
        sendMessageDto.setContactType(UserContactTypeEnum.GROUP.getType());
        sendMessageDto.setContactId(userContact.getContactId());
        sendUtils.sendMessage(sendMessageDto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer applyAddContact(String userId, String nickName, String contactId, String applyInfo) {
        UserContactTypeEnum typeEnum = DataTool.getContactTypeEnum(contactId);
        // 校验是否是自己
        DataTool.checkContactIdIsOwn(userId, contactId);
        UserContact userContact = userContactMapper.selectOne(new LambdaQueryWrapper<UserContact>().eq(UserContact::getUserId, userId).eq(UserContact::getContactId, contactId));
        if (userContact != null) {
            throw new BusinessException(ResultCode.BusinessError, typeEnum.equals(UserContactTypeEnum.USER) ? "已经是好友了" : "已加入该群聊");
        }
        Long Time = new Date().getTime();
        Integer joinType;
        UserContactApply userContactApply = new UserContactApply();
        userContactApply.setApplyUserId(userId);
        userContactApply.setStatus(ContactApplyStatusEnum.INIT.getStatus());
        userContactApply.setLastApplyTime(Time);
        userContactApply.setApplyNickName(nickName);
        switch (typeEnum) {
            case USER:
                UserContact userContact1 = userContactMapper.selectOne(new LambdaQueryWrapper<UserContact>().eq(UserContact::getUserId, contactId).eq(UserContact::getContactId, userId));
                if (userContact1 != null && userContact1.getStatus() == UserContactStatusEnum.BLACKLIST.getStatus()) {
                    throw new BusinessException(ResultCode.BusinessError, "对方已经将你加入黑名单");
                }
                R<UserInfoDto> userInfo4R = userServiceFeign.findUserInfo4(contactId);
                UserInfoDto userInfoDto = userInfo4R.getResult();
                if (!userInfo4R.getCode().equals(ResultCode.Success.getCode()) || userInfoDto == null) {
                    throw new BusinessException(ResultCode.BusinessError, "用户不存在");
                }
                joinType = userInfoDto.getUserInfo().getJoinType();
                LambdaQueryWrapper<UserContactApply> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(UserContactApply::getApplyUserId, userId);
                queryWrapper.eq(UserContactApply::getReceiveUserId, contactId);
                queryWrapper.eq(UserContactApply::getStatus, ContactApplyStatusEnum.INIT.getStatus());
                UserContactApply userContactApply1 = userContactApplyMapper.selectOne(queryWrapper);
                if (userContactApply1 != null) {
                    return joinType;
                }
                userContactApply.setReceiveUserId(contactId);
                userContactApply.setContactType(typeEnum.getType());
                userContactApply.setApplyInfo(DataTool.getApplyInfo(typeEnum, "", nickName, applyInfo));
                if (joinType == JoinTypeEnum.JOIN.getJoinType()) {
                    UserContact userContact2 = new UserContact(userContactApply.getApplyUserId(), userId, UserContactTypeEnum.USER.getType(), Time, UserContactStatusEnum.FRIEND.getStatus(), Time);
                    UserContact userContact3 = new UserContact(userId, userContactApply.getApplyUserId(), UserContactTypeEnum.USER.getType(), Time, UserContactStatusEnum.FRIEND.getStatus(), Time);
                    save(userContact2);
                    LambdaQueryWrapper<UserContact> eq = new LambdaQueryWrapper<UserContact>().eq(UserContact::getUserId, userId).eq(UserContact::getContactId, userContactApply.getApplyUserId());
                    UserContact userContact4 = userContactMapper.selectOne(eq);
                    if (userContact4 == null) {
                        save(userContact3);
                    } else {
                        userContact4.setStatus(UserContactStatusEnum.FRIEND.getStatus());
                        userContact4.setLastUpdateTime(Time);
                        userContactMapper.update(userContact4, eq);
                    }

                    ArrayList<Session> sessionList = new ArrayList<>();
                    String sessionId = Md5Util.Md5Method(new String[]{userId, contactId});
                    Session session = new Session(userId, contactId, sessionId, userInfoDto.getUserInfo().getNickName());
                    Session session2 = new Session(contactId, userId, sessionId, nickName);
                    sessionList.add(session);
                    sessionList.add(session2);
                    chatServiceFeign.addSessionList(sessionList);

                    ChatSession chatSession = new ChatSession(sessionId, MessageTypeEnum.ADD_FRIEND.getInitMessage(), Time);
                    chatServiceFeign.addChatSession(chatSession);

                    ArrayList<ChatMessage> chatMessageList = new ArrayList<>();
                    ChatMessage chatMessage = new ChatMessage(
                            sessionSeq.next(sessionId),
                            sessionId,
                            MessageTypeEnum.ADD_FRIEND.getType(),
                            MessageTypeEnum.ADD_FRIEND.getInitMessage(),
                            userId,
                            nickName,
                            Time,
                            contactId,
                            UserContactTypeEnum.USER.getType(),
                            MessageStatusEnum.FLUSH.getStatus()
                    );
                    ChatMessage chatMessage2 = new ChatMessage(
                            sessionSeq.next(sessionId),
                            sessionId,
                            MessageTypeEnum.CHAT.getType(),
                            userContactApply.getApplyInfo(),
                            userId,
                            nickName,
                            Time,
                            contactId,
                            UserContactTypeEnum.USER.getType(),
                            MessageStatusEnum.FLUSH.getStatus()
                    );
                    chatMessageList.add(chatMessage);
                    chatMessageList.add(chatMessage2);
                    chatServiceFeign.addChatMessageList(chatMessageList);

                    session.setChatSession(chatSession);
                    SendMessageDto<GroupInitData> sendMessageDto = new SendMessageDto<>();
                    GroupInitData groupInitData = new GroupInitData(session, chatMessageList);
                    sendMessageDto.setExtendData(groupInitData);
                    sendMessageDto.setMessageType(MessageTypeEnum.ADD_FRIEND.getType());
                    sendMessageDto.setContactType(UserContactTypeEnum.USER.getType());
                    sendMessageDto.setContactId(contactId);
                    sendUtils.sendMessage(sendMessageDto);
                    sendMessageDto.setContactId(userId);
                    sendUtils.sendMessage(sendMessageDto);
                    return joinType;
                }
                break;
            case GROUP:
                R<GroupInfo> groupInfoR = groupServiceFeign.getGroupInfo(contactId);
                GroupInfo groupInfo = groupInfoR.getResult();
                if (!groupInfoR.getCode().equals(ResultCode.Success.getCode()) || groupInfo == null) {
                    throw new BusinessException(ResultCode.BusinessError, "群聊不存在");
                }
                if (groupInfo.getStatus() == GroupStatusEnum.DIS_BAND.getType()) {
                    throw new BusinessException(ResultCode.BusinessError, "群聊已解散");
                }
                if (groupInfo.getStatus() == GroupStatusEnum.SHUT_DOWN.getType()) {
                    throw new BusinessException(ResultCode.BusinessError, "群聊已封禁");
                }
                joinType = groupInfo.getJoinType();
                LambdaQueryWrapper<UserContactApply> queryWrapper2 = new LambdaQueryWrapper<>();
                queryWrapper2.eq(UserContactApply::getApplyUserId, userId);
                queryWrapper2.eq(UserContactApply::getReceiveUserId, groupInfo.getGroupOwnerId());
                queryWrapper2.eq(UserContactApply::getGroupId, groupInfo.getGroupId());
                queryWrapper2.eq(UserContactApply::getStatus, ContactApplyStatusEnum.INIT.getStatus());
                UserContactApply userContactApply2 = userContactApplyMapper.selectOne(queryWrapper2);
                if (userContactApply2 != null) {
                    return joinType;
                }

                userContactApply.setReceiveUserId(groupInfo.getGroupOwnerId());
                userContactApply.setContactType(typeEnum.getType());
                userContactApply.setGroupId(groupInfo.getGroupId());
                userContactApply.setApplyInfo(DataTool.getApplyInfo(typeEnum, groupInfo.getGroupName(), nickName, applyInfo));

                if (joinType == JoinTypeEnum.JOIN.getJoinType()) {
                    UserContact userContact2 = new UserContact(userId, groupInfo.getGroupId(), typeEnum.getType(), Time, UserContactStatusEnum.FRIEND.getStatus(), Time);
                    int insert1 = userContactMapper.insert(userContact2);
                    DataTool.checkAffectRow(insert1);
                    sendUtils.JOIN_GROUP(userId, groupInfo.getGroupId());

                    String sessionId = Md5Util.Md5Method(new String[]{contactId});
                    Session session = new Session(userId, contactId, sessionId, groupInfo.getGroupName());
                    chatServiceFeign.addSession(session);

                    ChatSession chatSession = new ChatSession(sessionId, MessageTypeEnum.ADD_GROUP.getInitMessage().replace("%@", nickName), Time);
                    chatServiceFeign.updateChatSession(chatSession);

                    ArrayList<ChatMessage> chatMessageList = new ArrayList<>();
                    ChatMessage chatMessage = new ChatMessage(
                            sessionSeq.next(sessionId),
                            sessionId,
                            MessageTypeEnum.ADD_GROUP.getType(),
                            MessageTypeEnum.ADD_GROUP.getInitMessage().replace("%@", nickName),
                            userId,
                            nickName,
                            Time,
                            groupInfo.getGroupId(),
                            UserContactTypeEnum.GROUP.getType(),
                            MessageStatusEnum.FLUSH.getStatus()
                    );
                    chatMessageList.add(chatMessage);
                    chatServiceFeign.addChatMessage(chatMessage);

                    session.setChatSession(chatSession);
                    SendMessageDto<GroupInitData> sendMessageDto = new SendMessageDto<>();
                    GroupInitData groupInitData = new GroupInitData(session, chatMessageList);
                    sendMessageDto.setExtendData(groupInitData);

                    sendMessageDto.setMessageId(chatMessage.getMessageId());
                    sendMessageDto.setSessionId(sessionId);
                    sendMessageDto.setMessageType(MessageTypeEnum.ADD_GROUP.getType());
                    sendMessageDto.setMessageContent(chatMessage.getMessageContent());
                    sendMessageDto.setSendUserId(userId);
                    sendMessageDto.setSendUserNickName(nickName);
                    sendMessageDto.setSendTime(Time);
                    sendMessageDto.setContactId(contactId);
                    sendMessageDto.setContactType(UserContactTypeEnum.GROUP.getType());
                    sendMessageDto.setStatus(chatMessage.getStatus());
                    sendUtils.sendMessage(sendMessageDto);
                    return joinType;
                }
                break;
            default:
                throw new BusinessException(ResultCode.BusinessError);
        }
        int insert = userContactApplyMapper.insert(userContactApply);
        SendMessageDto<UserContactApply> sendMessageDto = new SendMessageDto<>();
        sendMessageDto.setExtendData(userContactApply);
        sendMessageDto.setMessageType(MessageTypeEnum.CONTACT_APPLY.getType());
        sendMessageDto.setContactType(UserContactTypeEnum.USER.getType());
        sendMessageDto.setContactId(userContactApply.getReceiveUserId());
        sendUtils.sendMessage(sendMessageDto);
        DataTool.checkAffectRow(insert);
        return joinType;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dealWithApply(String userId, String nickName, Integer applyId, Integer status) {
        ContactApplyStatusEnum byPrefix = ContactApplyStatusEnum.getByPrefix(status);
        if (byPrefix == null || byPrefix.equals(ContactApplyStatusEnum.INIT)) {
            throw new BusinessException(ResultCode.CODE_10017);
        }
        UserContactApply userContactApply = userContactApplyMapper.selectById(applyId);
        if (userContactApply == null || !userContactApply.getStatus().equals(ContactApplyStatusEnum.INIT.getStatus())) {
            throw new BusinessException(ResultCode.CODE_10017);
        }
        long Time = new Date().getTime();
        switch (byPrefix) {
            case AGREE:
                UserContactTypeEnum typeEnum = UserContactTypeEnum.getByType(userContactApply.getContactType());
                String nickName1 = userServiceFeign.findUserInfo4(userContactApply.getApplyUserId()).getResult().getUserInfo().getNickName();
                switch (typeEnum) {
                    case USER:
                        UserContact userContact2 = new UserContact(userContactApply.getApplyUserId(), userId, UserContactTypeEnum.USER.getType(), Time, UserContactStatusEnum.FRIEND.getStatus(), Time);
                        UserContact userContact3 = new UserContact(userId, userContactApply.getApplyUserId(), UserContactTypeEnum.USER.getType(), Time, UserContactStatusEnum.FRIEND.getStatus(), Time);
                        save(userContact2);
                        LambdaQueryWrapper<UserContact> eq = new LambdaQueryWrapper<UserContact>().eq(UserContact::getUserId, userId).eq(UserContact::getContactId, userContactApply.getApplyUserId());
                        UserContact userContact = userContactMapper.selectOne(eq);
                        if (userContact == null) {
                            save(userContact3);
                        } else {
                            userContact.setStatus(UserContactStatusEnum.FRIEND.getStatus());
                            userContact.setLastUpdateTime(Time);
                            userContactMapper.update(userContact, eq);
                        }

                        String sessionId = Md5Util.Md5Method(new String[]{userId, userContactApply.getApplyUserId()});
                        ArrayList<Session> sessionList = new ArrayList<>();
                        Session session = new Session(userContactApply.getApplyUserId(), userId, sessionId, nickName);
                        Session session2 = new Session(userId, userContactApply.getApplyUserId(), sessionId, nickName1);
                        sessionList.add(session);
                        sessionList.add(session2);
                        chatServiceFeign.addSessionList(sessionList);

                        ChatSession chatSession = new ChatSession(sessionId, MessageTypeEnum.ADD_FRIEND.getInitMessage(), Time);
                        chatServiceFeign.addChatSession(chatSession);

                        ArrayList<ChatMessage> chatMessageList = new ArrayList<>();
                        ChatMessage chatMessage = new ChatMessage(
                                sessionSeq.next(sessionId),
                                sessionId,
                                MessageTypeEnum.ADD_FRIEND.getType(),
                                MessageTypeEnum.ADD_FRIEND.getInitMessage(),
                                userContactApply.getApplyUserId(),
                                nickName1,
                                Time,
                                userId,
                                UserContactTypeEnum.USER.getType(),
                                MessageStatusEnum.FLUSH.getStatus()
                        );
                        ChatMessage chatMessage2 = new ChatMessage(
                                sessionSeq.next(sessionId),
                                sessionId,
                                MessageTypeEnum.CHAT.getType(),
                                userContactApply.getApplyInfo(),
                                userContactApply.getApplyUserId(),
                                nickName1,
                                Time,
                                userId,
                                UserContactTypeEnum.USER.getType(),
                                MessageStatusEnum.FLUSH.getStatus()
                        );
                        chatMessageList.add(chatMessage);
                        chatMessageList.add(chatMessage2);
                        chatServiceFeign.addChatMessageList(chatMessageList);


                        session.setChatSession(chatSession);
                        SendMessageDto<GroupInitData> sendMessageDto = new SendMessageDto<>();
                        GroupInitData groupInitData = new GroupInitData(session, chatMessageList);
                        sendMessageDto.setExtendData(groupInitData);
                        sendMessageDto.setMessageType(MessageTypeEnum.ADD_FRIEND.getType());
                        sendMessageDto.setContactType(UserContactTypeEnum.USER.getType());
                        sendMessageDto.setContactId(userId);
                        sendUtils.sendMessage(sendMessageDto);
                        sendMessageDto.setContactId(userContactApply.getApplyUserId());
                        sendUtils.sendMessage(sendMessageDto);
                        break;
                    case GROUP:
                        R<GroupInfo> groupInfoR = groupServiceFeign.getGroupInfo(userContactApply.getGroupId());
                        GroupInfo groupInfo = groupInfoR.getResult();
                        if (!groupInfoR.getCode().equals(ResultCode.Success.getCode()) || groupInfo == null) {
                            throw new BusinessException(ResultCode.BusinessError, "群聊不存在");
                        }
                        if (groupInfo.getStatus() == GroupStatusEnum.DIS_BAND.getType()) {
                            throw new BusinessException(ResultCode.BusinessError, "群聊已解散");
                        }
                        if (groupInfo.getStatus() == GroupStatusEnum.SHUT_DOWN.getType()) {
                            throw new BusinessException(ResultCode.BusinessError, "群聊已封禁");
                        }

                        UserContact userContact4 = new UserContact(userContactApply.getApplyUserId(), userContactApply.getGroupId(), typeEnum.getType(), Time, UserContactStatusEnum.FRIEND.getStatus(), Time);
                        int insert1 = userContactMapper.insert(userContact4);
                        DataTool.checkAffectRow(insert1);
                        sendUtils.JOIN_GROUP(userContactApply.getGroupId(), userContactApply.getApplyUserId());

                        String sessionId2 = Md5Util.Md5Method(new String[]{userContactApply.getGroupId()});
                        Session session3 = new Session(userContactApply.getApplyUserId(), userContactApply.getGroupId(), sessionId2, groupInfo.getGroupName());
                        chatServiceFeign.addSession(session3);

                        ChatSession chatSession2 = new ChatSession(sessionId2, MessageTypeEnum.ADD_GROUP.getInitMessage().replace("%@", nickName1), Time);
                        chatServiceFeign.updateChatSession(chatSession2);

                        ArrayList<ChatMessage> chatMessageList2 = new ArrayList<>();
                        ChatMessage chatMessage3 = new ChatMessage(
                                sessionSeq.next(sessionId2),
                                sessionId2,
                                MessageTypeEnum.ADD_GROUP.getType(),
                                MessageTypeEnum.ADD_GROUP.getInitMessage().replace("%@", nickName1),
                                userContactApply.getApplyUserId(),
                                nickName1,
                                Time,
                                userContactApply.getGroupId(),
                                typeEnum.getType(),
                                MessageStatusEnum.FLUSH.getStatus()
                        );
                        chatServiceFeign.addChatMessage(chatMessage3);

                        chatMessageList2.add(chatMessage3);
                        session3.setChatSession(chatSession2);
                        SendMessageDto<GroupInitData> sendMessageDto2 = new SendMessageDto<>();
                        GroupInitData groupInitData2 = new GroupInitData(session3, chatMessageList2);
                        sendMessageDto2.setExtendData(groupInitData2);

                        sendMessageDto2.setMessageId(chatMessage3.getMessageId());
                        sendMessageDto2.setSessionId(sessionId2);
                        sendMessageDto2.setMessageType(MessageTypeEnum.ADD_GROUP.getType());
                        sendMessageDto2.setMessageContent(chatMessage3.getMessageContent());
                        sendMessageDto2.setLastMessage(chatMessage3.getMessageContent());
                        sendMessageDto2.setSendUserId(userContactApply.getApplyUserId());
                        sendMessageDto2.setSendUserNickName(nickName1);
                        sendMessageDto2.setSendTime(Time);
                        sendMessageDto2.setContactId(userContactApply.getGroupId());
                        sendMessageDto2.setContactType(UserContactTypeEnum.GROUP.getType());
                        sendMessageDto2.setStatus(chatMessage3.getStatus());
                        sendUtils.sendMessage(sendMessageDto2);
                        break;
                    default:
                        throw new BusinessException(ResultCode.CODE_10017);
                }
                LambdaUpdateWrapper<UserContactApply> updateWrapper2 = new LambdaUpdateWrapper<>();
                updateWrapper2.eq(UserContactApply::getApplyId, applyId);
                updateWrapper2.set(UserContactApply::getStatus, ContactApplyStatusEnum.AGREE.getStatus());
                int update2 = userContactApplyMapper.update(null, updateWrapper2);
                DataTool.checkAffectRow(update2);
                break;
            case REJECT:
                userContactApply.setStatus(ContactApplyStatusEnum.REJECT.getStatus());
                int update = userContactApplyMapper.updateById(userContactApply);
                DataTool.checkAffectRow(update);
                break;
            case BLACKLIST:
                UserContactTypeEnum typeEnum2 = UserContactTypeEnum.getByType(userContactApply.getContactType());
                if (typeEnum2.equals(UserContactTypeEnum.GROUP)) {
                    throw new BusinessException(ResultCode.CODE_10017);
                }
                userContactApply.setStatus(ContactApplyStatusEnum.BLACKLIST.getStatus());
                int update1 = userContactApplyMapper.updateById(userContactApply);
                DataTool.checkAffectRow(update1);
                UserContact userContact = new UserContact(userId, userContactApply.getApplyUserId(), typeEnum2.getType(), Time, UserContactStatusEnum.BLACKLIST.getStatus(), Time);
                UserContact userContact1 = userContactMapper.selectOne(new LambdaQueryWrapper<UserContact>().eq(UserContact::getUserId, userId).eq(UserContact::getContactId, userContactApply.getApplyUserId()));
                if (userContact1 != null) {
                    LambdaUpdateWrapper<UserContact> updateWrapper = new LambdaUpdateWrapper<>();
                    updateWrapper.eq(UserContact::getUserId, userId).eq(UserContact::getContactId, userContactApply.getApplyUserId());
                    updateWrapper.set(UserContact::getStatus, UserContactStatusEnum.BLACKLIST.getStatus());
                    int i = userContactMapper.update(userContact, updateWrapper);
                    return;
                }
                int insert2 = userContactMapper.insert(userContact);
                DataTool.checkAffectRow(insert2);
                break;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<UserContact> addGroupUser(String userId, AddGroupUserDto addGroupUserDto) {
        isMyGroup(userId, addGroupUserDto.getGroupId(), "群主可以添加群成员");
        ArrayList<UserContact> userContactList = new ArrayList<>();
        Long Time = new Date().getTime();
        for (UserContact contact : addGroupUserDto.getUserContactList()) {
            UserContact userContact = new UserContact(contact.getContactId(), addGroupUserDto.getGroupId(), UserContactTypeEnum.GROUP.getType(), Time, UserContactStatusEnum.FRIEND.getStatus(), Time);
            userContactList.add(userContact);
            sendUtils.JOIN_GROUP(addGroupUserDto.getGroupId(), contact.getContactId());

        }
        boolean b = saveBatch(userContactList);
        DataTool.checkAffectRow(b ? 1 : 0);
        return userContactList;
    }

    @Override
    public void removeGroupUser(String userId, RemoveGroupUserDto groupUserDto) {
        isMyGroup(userId, groupUserDto.getGroupId(), "群主可以移除群成员");
        LambdaQueryWrapper<UserContact> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(UserContact::getUserId, (Object) groupUserDto.getUserIdList()).eq(UserContact::getContactId, groupUserDto.getGroupId());
        int delete = userContactMapper.delete(queryWrapper);
        DataTool.checkAffectRow(delete, "移除失败");

        // 删除会话
        chatServiceFeign.delGroupSessionBatch(groupUserDto.getUserIdList(), groupUserDto.getGroupId());
    }

    public void isMyGroup(String userId, String groupId, String msg) {
        R<GroupInfo> groupInfo = groupServiceFeign.getGroupInfo(groupId);
        if (!groupInfo.getCode().equals(ResultCode.Success.getCode()) || groupInfo.getResult() == null) {
            throw new BusinessException(ResultCode.BusinessError, "群聊不存在");
        }
        if (!groupInfo.getResult().getGroupOwnerId().equals(userId)) {
            throw new BusinessException(ResultCode.BusinessError, msg);
        }
    }
}
